import Vue from 'vue'
import Router from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getAuthToken } from '../utils/browser'
import { HOME_PATH, LOGIN_PATH } from '../const/route-path'
import store from '../store'
import Default from '../components/home/Default'

// 进度条的配置
NProgress.configure({ showSpinner: false })

/**
 * 重写路由的push方法  TODO 解决导航重复的问题
 */
const routerPush = Router.prototype.push

Router.prototype.push = function push(location) {
  return routerPush.call(this, location).catch(err => console.log(err))
}

Vue.use(Router)

// 这些路由是系统公共开放的，不需要用户权限
export const publicRoutes = [
  {
    path: LOGIN_PATH,
    name: 'Login',
    component: () => import('../components/home/Login')
  }
]

// 开始构建私有路由，这些路由是私有的，需要配置用户权限
const modulesFiles = require.context('./modules', true, /\.js$/)
// 得到的是挂载菜单根节点下，故为子路由
const defaultRouteChildren = modulesFiles.keys().reduce((modules, modulePath) => {
  const value = modulesFiles(modulePath)
  modules = modules.concat(value.default)
  return modules
}, [])

// 左侧菜单里所有路由打包为一个对象，但是加入到路由还是要以数组格式
// router内部会concat处理所有数组
// 如果你希望有些路由不在左侧菜单下，那么你可以写一个新的路由对象打包它们
export const privateRoutes = [
  {
    path: '/',
    redirect: '/PersonCenter',
    component: Default,
    children: defaultRouteChildren
  }
]

// 这些路由是放在最后并且必须的，如404
export const lastRequiredRoutes = [
  {
    alias: '*',
    path: '/Page404',
    component: () => import('../components/404/Page404')
  }
]

const createRouter = () =>
  new Router({
    scrollBehavior: () => ({ x: 0, y: 0 }),
    routes: publicRoutes
  })
// 创建路由实例
const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
// this.$router.options.routes = []
// this.$router.addRoutes([])
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

// 路由导航 - Before
router.beforeEach(async (to, from, next) => {
  // 记录旧的路径
  const oldPath = to.path
  // 进度条开始
  NProgress.start()
  // 设置当前菜单
  store.commit('menu/SET_SESSION_ACTIVE_MENU', to.path)
  const hasToken = getAuthToken()
  if (hasToken) {
    // 已经登录认证，则开始登录后数据初始化
    try {
      // 权限判断登录后数据初始化状态
      const hasLoginInited = store.getters['login/getLoginInitialized']
      if (!hasLoginInited) {
        // 未登录初始化，则调用初始化方法
        await store.dispatch('login/initAfterLogin')
        // 重新路由
        return next({ ...to, replace: true })
      }
      // 初始化数据已经存在或加载成功完毕，则继续路由跳转
      if (to.path === LOGIN_PATH) {
        next({ path: HOME_PATH })
      } else {
        next()
      }
    } catch (error) {
      // 登录后数据初始化失败，退出登录
      store.dispatch('login/logout', oldPath)
    }
  } else {
    // 未登录认证，拦截跳转到登录页面，为了防止登录后不初始化，重置状态
    store.commit('login/REMOVE_LOGIN_INITIALIZED')
    if (to.path === LOGIN_PATH) {
      next()
    } else {
      if (to.path === HOME_PATH) {
        next(LOGIN_PATH)
      } else {
        next(LOGIN_PATH + '?redirect=' + to.path)
      }
    }
  }
})

// 路由导航 - After
router.afterEach((to, from) => {
  NProgress.done()
})
export default router
